﻿using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.VisualStudio.TemplateWizard;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.Win32;

namespace CodeEndeavors.Templates.Wizard
{
    public class TemplateWizard : IWizard
    {
        private UserInputForm inputForm;
        private DTE _dte;

        // This method is called before opening any item that 
        // has the OpenInEditor attribute.
        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
            try
            {

                if (project == null)    //not sure why this event is fired twice for multi-project templates.  one time it has no project 
                    return;

                AddProjectDependencies();

                //project.Properties.Item("AssemblyName").Value = Properties.Settings.Default.CompanyNamespace + "." + project.Properties.Item("AssemblyName").Value;
                if (project.Name.IndexOf("_Xap") == -1) //xap projects don't like an assembly name with a prefix...  the initial generation of the .g file does not load right (InitializeComponent - System.Windows.Application.LoadComponent(this, new System.Uri("/[MISSINGCOMPANYHERE]DNNSilverlightModule1_Xap;component/Page.xaml", System.UriKind.Relative));
                {
                    project.Properties.Item("DefaultNamespace").Value = Properties.Settings.Default.CompanyNamespace; 
                }
                else
                {
                    if (project.CodeModel.Language != CodeModelLanguageConstants.vsCMLanguageVB)
                        project.Properties.Item("DefaultNamespace").Value = Properties.Settings.Default.CompanyNamespace; //change default namespace for non-Xap files.  their custom tools for VB don't like changed namespaces (they require manual Run Custom Tool), so allow the normal namespace of Company.Project to stick!
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            //CopyFiles();

        }

        private void AddProjectDependencies()
        {
            //hack for adding build dependency for Xap file
            var projects = new Dictionary<string, EnvDTE.Project>();
            foreach (EnvDTE.Project p in _dte.Solution.Projects)
            {
                projects[p.Name] = p;
            }
            foreach (var name in projects.Keys)
            {
                foreach (var name2 in projects.Keys)
                {
                    if (name != name2)
                    {
                        if (name.IndexOf("_Xap") > -1)
                            _dte.Solution.SolutionBuild.BuildDependencies.Item(projects[name2].UniqueName).AddProject(projects[name].UniqueName);
                        else if (name2.IndexOf("_Xap") > -1)
                            _dte.Solution.SolutionBuild.BuildDependencies.Item(projects[name].UniqueName).AddProject(projects[name2].UniqueName);
                    }
                }
            }

        }

        private void CopyFiles(string path)
        {
            DirectoryInfo projDir = new FileInfo(path).Directory;
            string libDir = projDir.FullName + @"\lib";
            if (!Directory.Exists(libDir))
                Directory.CreateDirectory(libDir);
            CopyDnnFile("DotNetNuke.dll", libDir);
            CopyDnnFile("DotNetNuke.WebUtility.dll", libDir);
            CopyDnnFile("System.Web.Extensions.dll", libDir, true);
            CopyDnnFile("Microsoft.ApplicationBlocks.Data.dll", libDir);

            //copy msbuild extensions to lib
            //MessageBox.Show(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
            var installPath = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Code Endeavors, LLC", "InstallPath", @"c:\").ToString();

            string msbuildPath = Path.Combine(libDir, "msbuild");
            if (!Directory.Exists(msbuildPath))
                Directory.CreateDirectory(msbuildPath);

            foreach (var fileName in Directory.GetFiles(installPath, "MSBuild*.*"))
            {
                var file = new FileInfo(fileName);
                SafeCopy(file.FullName, Path.Combine(msbuildPath, file.Name));
            }
            foreach (var fileName in Directory.GetFiles(installPath, "ICSharp*.*"))
            {
                var file = new FileInfo(fileName);
                SafeCopy(file.FullName, Path.Combine(msbuildPath, file.Name));
            }
        }

        private void SafeCopy(string from, string to)
        {
            SafeCopy(from, to, false);
        }

        private void SafeCopy(string from, string to, bool bypassError)
        {
            try
            {
                File.Copy(from, to, true);
            }
            catch (Exception ex)
            {
                if (bypassError == false)
                    MessageBox.Show(ex.Message);    //keep going!
            }
        }

        private void CopyDnnFile(string dnnFile, string libDir)
        {
            CopyDnnFile(dnnFile, libDir, false);
        }

        private void CopyDnnFile(string dnnFile, string libDir, bool bypassError)
        {
            string dnnBinDir = Path.Combine(Properties.Settings.Default.DotNetNukeDir, "bin");
            SafeCopy(Path.Combine(dnnBinDir, dnnFile), Path.Combine(libDir, dnnFile), bypassError);
        }

        // This method is only called for item templates,
        // not for project templates.
        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        // This method is called after the project is created.
        public void RunFinished()
        {
        }

        public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
        {
            try
            {

                _dte = automationObject as DTE;

                if (_dte.Globals.get_VariableExists("replacements"))
                {
                    var dict = _dte.Globals["replacements"] as Dictionary<string, string>;
                    foreach (var key in dict.Keys)
                        replacementsDictionary[key] = dict[key];
                    
                    return; //we have replacements already - hack for multi-project replacements
                }

                // Display a form to the user. The form collects 
                // input for the custom message.
                inputForm = new UserInputForm();
                if (inputForm.ShowDialog() == DialogResult.OK)
                {

                    // Add custom parameters.
                    replacementsDictionary.Add("$YourCompany$", Properties.Settings.Default.CompanyNamespace);
                    replacementsDictionary.Add("$DotNetNukeDir$", Properties.Settings.Default.DotNetNukeDir);
                    replacementsDictionary.Add("$owner$", Properties.Settings.Default.OwnerName);
                    replacementsDictionary.Add("$organization$", Properties.Settings.Default.Organization);
                    replacementsDictionary.Add("$supporturl$", Properties.Settings.Default.SupportUrl);
                    replacementsDictionary.Add("$supportemail$", Properties.Settings.Default.SupportEmail);
                    CopyFiles(replacementsDictionary["$destinationdirectory$"]);

                    _dte.Globals["replacements"] = replacementsDictionary;

                }
                else
                    throw new WizardCancelledException("The wizard has been cancelled by the user.");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            //replacementsDictionary["$safeprojectname$"] = inputForm.CompanyNamespace;
        }

        // This method is only called for item templates,
        // not for project templates.
        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }
    }
}